import numpy as np
from sklearn import datasets
import matplotlib.pyplot as plt


# 激活函数
# Sigmoid型函数是指一类S型曲线函数，为两端饱和函数。常用的Sigmoid型函数有Logistic函数和Tanh函数.
def Logistic(x):
    return 1.0 / (1 + np.exp(-x))


# Tanh函数也可以用分段函数hard-tanh(𝑥)来近似
def Tanh(x):
    return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))


# ReLU（Rectified Linear Unit，修正线性单元),也叫Rectifier函数，是目前深度神经网络中经常使用的激活函数
# ReLU实际上是一个斜坡（ramp）函数
# ReLU优点：高效、单侧抑制、宽兴奋边界、很好的稀疏性，缓解了神经网络的梯度消失问题，加速梯度下降的收敛速度
# ReLU缺点：输出是非零中心化的，给后一层的神经网络引入偏置偏移，会影响梯度下降的效率，训练时比较容易“死亡“
def ReLU(x):
    return np.maximum(0, x)


# 初始化网络，定义5层神经网络，2-4-5-3-2
def init_network():
    net = {'W1': np.array([[0.1, 0.2, 0.3, 0.4],
                           [0.4, 0.5, 0.6, 0.5]]),
           'b1': np.array([0.1, 0.2, 0.3, 0.1]),
           'W2': np.array([[-0.6, 0.5, 0.4],
                           [0.6, -0.5, 0.4],
                           [0.6, -0.5, 0.5],
                           [0.5, 0.5, -0.5]]),
           'b2': np.array([0.1, 0.2, 0.3]),
           'W3': np.array([[-0.6, 0.5],
                           [0.6, -0.6],
                           [-0.5, 0.5]]),
           'b3': np.array([0.3, 0.2])}
    return net


# 网络向前实现
def forward_net(net, x):
    W1 = net['W1']
    b1 = net['b1']
    W2 = net['W2']
    b2 = net['b2']
    W3 = net['W3']
    b3 = net['b3']
    z1 = np.dot(x, W1) + b1
    a1 = Logistic(z1)
    z2 = np.dot(a1, W2) + b2
    a2 = ReLU(z2)
    z3 = np.dot(a2, W3) + b3
    a3 = Tanh(z3)
    return a3


# 运行
NET = init_network()
X = np.array([2, 3])
print(forward_net(NET, X))
